package com.lxs.mall.service.Impl;

import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.lxs.mall.common.Constant;
import com.lxs.mall.exception.LxsMallException;
import com.lxs.mall.exception.LxsMallExceptionEnum;
import com.lxs.mall.model.dao.ProductMapper;
import com.lxs.mall.model.pojo.Product;
import com.lxs.mall.model.query.ProductListQuery;
import com.lxs.mall.model.request.AddProductReq;
import com.lxs.mall.model.request.ProductListReq;
import com.lxs.mall.model.request.UpdateProductReq;
import com.lxs.mall.model.vo.CategoryVo;
import com.lxs.mall.service.CategoryService;
import com.lxs.mall.service.ProductService;
import com.lxs.mall.util.ExcelUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author 小松
 */
@Service
public class ProductServiceImpl implements ProductService {
    @Resource
    ProductMapper productMapper;
    @Resource
    CategoryService categoryService;

    @Override
    public void add(AddProductReq addProductReq) {
        Product product = new Product();
        BeanUtils.copyProperties(addProductReq, product);
        Product productOld = productMapper.selectByName(addProductReq.getName());
        if (productOld != null) {
            throw new LxsMallException(LxsMallExceptionEnum.NAME_EXISTED);
        }
        int count = productMapper.insertSelective(product);
        if (count == 0) {
            throw new LxsMallException(LxsMallExceptionEnum.CREATE_FAILED);
        }
    }

    @Override
    public void update(UpdateProductReq updateProductReq) {
        Product product = new Product();
        BeanUtils.copyProperties(updateProductReq, product);
        Product productOld = productMapper.selectByName(product.getName());
        if (productOld != null && !productOld.getId().equals(product.getId())) {
            throw new LxsMallException(LxsMallExceptionEnum.UPDATE_FAILED);
        }
        int count = productMapper.updateByPrimaryKeySelective(product);
        if (count == 0) {
            throw new LxsMallException(LxsMallExceptionEnum.UPDATE_FAILED);
        }
    }

    @Override
    public void delete(Integer id) {
        Product productOld = productMapper.selectByPrimaryKey(id);
        if (productOld == null) {
            throw new LxsMallException(LxsMallExceptionEnum.DELETE_FAILED);
        }
        int count = productMapper.deleteByPrimaryKey(id);
        if (count == 0) {
            throw new LxsMallException(LxsMallExceptionEnum.DELETE_FAILED);
        }
    }

    @Override
    public void batchUpdateSellStatus(Integer[] ids, Integer sellStatus) {
        productMapper.batchUpdateSellStatus(ids, sellStatus);
    }

    @Override
    public PageInfo<Product> listForAdmin(Integer pageNum, Integer pageSize) {
        PageMethod.startPage(pageNum, pageSize);
        List<Product> products = productMapper.selectListForAdmin();
        return new PageInfo<>(products);
    }

    @Override
    public Product detail(Integer id) {
        return productMapper.selectByPrimaryKey(id);
    }

    @Override
    public PageInfo<Product> list(ProductListReq productListReq) {
        //构建query对象
        ProductListQuery productListQuery = new ProductListQuery();
        //搜索处理
        if (!StringUtils.isEmpty(productListReq.getKeyword())) {
            String keyword = "%" + productListReq.getKeyword() + "%";
            productListQuery.setKeyword(keyword);
        }
        //目录处理:如果查某个目录下的商品，不仅是需要查出该目录下的，还要把所有子目录的所有商品都查出来，
        // 所以要拿到一个目录id的List
        if (productListReq.getCategoryId() != null) {
            List<CategoryVo> categoryVoList = categoryService.listCategoryForCustomer(
                    productListReq.getCategoryId());
            ArrayList<Integer> categoryIds = new ArrayList<>();
            categoryIds.add(productListReq.getCategoryId());
            getCategoryIds(categoryVoList, categoryIds);
            productListQuery.setCategoryIds(categoryIds);
        }
        //排序处理
        String orderBy = productListReq.getOrderBy();
        if (Constant.ProductListOrderBy.PRICE_ASC_DESC.contains(orderBy)) {
            PageMethod.startPage(productListReq.getPageNum(), productListReq.getPageSize(), orderBy);
        } else {
            PageMethod.startPage(productListReq.getPageNum(), productListReq.getPageSize());
        }
        List<Product> productList = productMapper.selectList(productListQuery);
        return new PageInfo<>(productList);
    }

    public void getCategoryIds(List<CategoryVo> categoryVoList, List<Integer> categoryIds) {
        for (CategoryVo categoryVo : categoryVoList) {
            if (categoryVo != null) {
                categoryIds.add(categoryVo.getId());
                getCategoryIds(categoryVo.getChildCategory(), categoryIds);
            }
        }
    }

    @Override
    public void addProductByExcel(File destFile) throws IOException {
        List<Product> productList = readProductByExcel(destFile);
        for (Product product : productList) {
            Product productOld = productMapper.selectByName(product.getName());
            if (productOld != null) {
                throw new LxsMallException(LxsMallExceptionEnum.NAME_EXISTED);
            }
            int count = productMapper.insertSelective(product);
            if (count == 0) {
                throw new LxsMallException(LxsMallExceptionEnum.CREATE_FAILED);
            }
        }
    }

    /**
     * 把文件转换成商品列表
     * @param destFile 文件
     * @return  List<Product>
     * @throws IOException
     */
    public List<Product> readProductByExcel(File destFile) throws IOException {
        List<Product> productList = new ArrayList<>();
        FileInputStream fileInputStream = new FileInputStream(destFile);

        XSSFWorkbook xssfWorkbook = new XSSFWorkbook(fileInputStream);
        XSSFSheet firstSheet = xssfWorkbook.getSheetAt(0);
        Iterator<Row> rowIterator = firstSheet.iterator();
        while (rowIterator.hasNext()) {
            Row nextRow = rowIterator.next();
            Iterator<Cell> cellIterator = nextRow.cellIterator();
            Product product = new Product();

            while (cellIterator.hasNext()) {
                Cell nextCell = cellIterator.next();
                int columnIndex = nextCell.getColumnIndex();
                int intValue;
                switch (columnIndex) {
                    case 0:
                        product.setName(String.valueOf(ExcelUtil.getCellValue(nextCell)));
                        break;
                    case 1:
                        product.setImage(String.valueOf(ExcelUtil.getCellValue(nextCell)));
                        break;
                    case 2:
                        product.setDetail(String.valueOf(ExcelUtil.getCellValue(nextCell)));
                        break;
                    case 3:
                        intValue = ((Double) ExcelUtil.getCellValue(nextCell)).intValue();
                        product.setCategoryId(intValue);
                        break;
                    case 4:
                        intValue = ((Double) ExcelUtil.getCellValue(nextCell)).intValue();
                        product.setPrice(intValue);
                        break;
                    case 5:
                        intValue = ((Double) ExcelUtil.getCellValue(nextCell)).intValue();
                        product.setStock(intValue);
                        break;
                    case 6:
                        intValue = ((Double) ExcelUtil.getCellValue(nextCell)).intValue();
                        product.setStatus(intValue);
                        break;
                    default:
                        break;
                }
            }
            productList.add(product);
        }
        xssfWorkbook.close();
        fileInputStream.close();
        return productList;
    }
}
